//
//  LeCubeRenderer.cpp
//  Leste
//
//  Created by 王乐 on 2022/1/26.
//

#include "LeCubeRenderer.h"
#include "glad/glad.h"

#include "LeVBOManager.h"
#include "LeUtils.h"

#include "LeCameraManager.h"

#include "LeLight.h"

LeCubeRenderer::LeCubeRenderer() {
    
}

LeCubeRenderer::~LeCubeRenderer()  {
}

void LeCubeRenderer::preLoopRender() { 
    
    unsigned int VBO;
    LeVBOManager::findVBO("Cube", VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);
    
    // load textures (we now use a utility function to keep the code more organized)
    // -----------------------------------------------------------------------------
    diffuseMap = LeTextureLoader().loadTexture("/Users/wangle/CLionProjects/Leste/res/container2.png");
    specularMap = LeTextureLoader().loadTexture("/Users/wangle/CLionProjects/Leste/res/container2_specular.png");

    // shader configuration
    // --------------------
    m_Shader.useShader();
    m_Shader.setInt("material.diffuse", 0);
    m_Shader.setInt("material.specular", 1);
}

void LeCubeRenderer::render() {
    glm::mat4 projection =  LeCameraManager::getProjectionMatrix();
    glm::mat4 view = LeCameraManager::getViewMatrix();
    
    // be sure to activate shader when setting uniforms/drawing objects
    m_Shader.useShader();
    m_Shader.setVec3("viewPos", LeCameraManager::getCameraPosition().x, LeCameraManager::getCameraPosition().y, LeCameraManager::getCameraPosition().z);
    
    m_Shader.setFloat("material.shininess", 32.0f);
    
    m_Shader.setVec3("light.ambient", 0.5f, 0.5f, 0.5f);
    m_Shader.setVec3("light.diffuse", 0.9f, 0.9f, 0.9f);
    m_Shader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
    m_Shader.setVec3("light.position", lightPos.x, lightPos.y, lightPos.z);

    m_Shader.setMat4("projection", projection);
    m_Shader.setMat4("view", view);


    glm::mat4 model = m_GameObject->m_Transform.getModelMatrix();
    m_Shader.setMat4("model", model);

    // bind diffuse map
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, diffuseMap);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, specularMap);
    
    // render the cube
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
}

void LeCubeRenderer::renderSelection()
{
    glm::mat4 projection =  LeCameraManager::getProjectionMatrix();
    glm::mat4 view = LeCameraManager::getViewMatrix();

    m_SelectionShader.useShader();
    m_SelectionShader.setMat4("projection", projection);
    m_SelectionShader.setMat4("view", view);

    glm::mat4 model = m_GameObject->m_Transform.getModelMatrix();
    m_SelectionShader.setMat4("model", model);

    m_SelectionShader.setInt("code", m_GameObject->ID);

    // render the cube
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
}

void LeCubeRenderer::postLoopRender() { 
    glDeleteVertexArrays(1, &VAO);
}